﻿/*+========================================================
File:		RunningMan.cpp
Sumary:		Hiện thực hóa các phương thức của lớp CRunningMan
========================================================+*/

#include "RunningMan.h"
#include "PlayState.h"

CRunningMan::CRunningMan(D3DXVECTOR2 pos, int id, int typeId, bool direction) :
CMoveableObject(pos, id, typeId)
{
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_ENEMY_RUN);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_ENEMY_JUMP);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_ENEMY_DIE);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_ENEMY_FALL_IN_WATER);
	m_bIsRight = direction;
	m_bIsFired = false;
	m_nStatus = ENEMY_JUMP;
	m_fTimeDie = 0.0f;
	timeFire = 1.0f;
	m_pGun = new CGun(ID_ENEMY_SMALL_WHITE_BULLET, 1, 1);
	for (int i = 0; i < 3; i++)
	{
		m_aSprite[i] = new CSprite(*m_pResourceManager->GetSprite(ID_SPRITE_ENEMY_RUN + i));
	}
	m_posInit = pos;
	m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_ENEMY_JUMP);
	m_box.width = 30;
	m_box.height = 62;
	m_v.y = ENEMY_VY;
	m_nCount = 0;
	if (m_bIsRight)
		m_v.x = -ENEMY_VX;
	else
		m_v.x = ENEMY_VX;
	m_a.y = GRAVITY;
	srand(time(NULL));
	m_pTextureBox = m_pResourceManager->GetTexture(ID_TEXTURE_BILL_BOX);
}

CRunningMan::~CRunningMan()
{
	if (m_pGun)
		delete m_pGun;
	for (int i = 0; i < 3; i++)
	{
		delete m_aSprite[i];
	}
}

void CRunningMan::Update(float timeFrame)
{
	if (!m_bIsLive)
	{
		if (m_fTimeDie > 0)
		{
			m_fTimeDie -= timeFrame;
			m_v += m_a * timeFrame;
			m_pos.y += m_v.y * timeFrame;
		}
		else if (m_fTimeDie < 0)
		{
			m_fTimeDie = 0.0f;
			this->Explode();
		}
		if (!m_bIsFallInWater)
		{
			m_pSprite = m_aSprite[ENEMY_DIE];
		}
		return;
	}
	m_pSprite->Update(timeFrame);
	switch (m_nStatus)
	{
	case ENEMY_RUN:
	{
		if (m_bIsFiring)
		{
			m_v.x = 0.0f;
			m_v.y = 0.0f;
			m_pSprite = m_aSprite[ENEMY_DIE];
		}
		else
		{
			m_pSprite = m_aSprite[ENEMY_RUN];
		}

		if (!m_bIsFired)
		{
			D3DXVECTOR2 vpPos = CViewport::GetInstance()->GetPosition();
			Box box = { vpPos.x + 50, vpPos.y - 50, SCREEN_WIDTH - 100, SCREEN_HEIGHT - 100, 0.0f, 0.0f };
			if (this->GetBox().IsInside(box))
			{
				if (g_nCurentLvl == ID_LEVEL2)
				{
					srand(time(NULL));
					if (!m_bIsFiring)
					{
						int a = rand() % 100;
						if (rand() % 100 > 80)
						{
							Fire();
						}
					}
				}
				else if (g_nCurentLvl == ID_LEVEL3)
				{
					srand(time(NULL));
					if (!m_bIsFiring)
						if (rand() % 100 > 40)
						{
							Fire();
						}
				}
			}
		}
	}
		break;
	case ENEMY_JUMP:
		m_pSprite = m_aSprite[ENEMY_JUMP];
		if (m_bIsJumping)
		{
			m_v.y = ENEMY_VY;
			m_bIsJumping = false;
		}
		break;
		/*case ENEMY_FIRE:
			m_v.x = 0;
			m_v.y = 0;
			m_pSprite = m_aSprite[ENEMY_DIE];
			break;*/
	case ENEMY_DIE:
		if (!m_bIsFallInWater)
			m_pSprite = m_aSprite[ENEMY_DIE];
		break;
	}
	if ((m_pos.x + m_pSprite->GetWidth() / 2 < CViewport::GetInstance()->GetPosition().x - 70)
		|| (m_pos.x > CViewport::GetInstance()->GetPosition().x + SCREEN_WIDTH + 70)
		|| (m_pos.y > CViewport::GetInstance()->GetPosition().y)
		|| (m_pos.y < 0.0f))
	{
		if (rand() % 100 < 95)
			Kill();
		else
		{
			m_bIsRight = !m_bIsRight;
			m_v.x = -m_v.x;
		}
	}

	if (m_bIsFiring)
	{
		if (timeFire > 0)
		{
			timeFire -= timeFrame;
		}
		else
		{
			timeFire = 0.0f;
			m_bIsFiring = false;

			if (m_bIsRight)
				m_v.x = -ENEMY_VX;
			else
				m_v.x = ENEMY_VX;
		}
	}

	UpdateBox(timeFrame);
}

void CRunningMan::UpdateCollision(vector<CGameObject*> vecGameObjs, float timeFrame)
{
	if (!m_bIsLive)
		return;
	float timeCollision = timeFrame;

	CGameObject* objCollision = NULL; // Đối tượng va chạm sớm nhất.
	float normalx = 0.0f, normaly = 0.0f;


	// Xử lí va chạm với đạn của Bill
	for (int i = 0; i < CPlayState::s_billBullets.size(); i++)
	{
		if (CPlayState::s_billBullets[i]->IsLive())
		{
			float t = CheckCollision(CPlayState::s_billBullets[i], normalx, normaly, timeFrame);

			if (t < timeFrame && t < timeCollision)
			{
				// Tìm đối tượng và thời gian va chạm sớm nhất.
				timeCollision = t;
				objCollision = CPlayState::s_billBullets[i];
			}
		}
	}

	// Xử lí va chạm
	if (objCollision != NULL)
	{
		m_v.y = 200.0f;
		m_fTimeDie = 0.18f;
		m_nStatus = ENEMY_DIE;
		m_bIsLive = false;
		objCollision->Kill();
		g_nScore += 100;
		return;
	}


	CGameObject* topObj = NULL;
	float toptime = timeFrame;
	CGameObject* currentObj = NULL;
	normalx = 0.0f, normaly = 0.0f;
	timeCollision = timeFrame;
	for (int i = 0; i < vecGameObjs.size(); i++)
	{
		if (vecGameObjs[i]->IsLive())
		{
			float timeCollision = CheckCollision(vecGameObjs[i], normalx, normaly, timeFrame);
			if (timeCollision < timeFrame) //Xảy ra va chạm
			{
				switch (vecGameObjs[i]->GetTypeId())
				{
				case ID_GRASS:
				case ID_GRASS_CAN_FALL:
					if (normaly == 1)
					{
						m_nStatus = ENEMY_RUN;
						m_pos.y += m_v.y * timeCollision;
						m_pos.y += 0.1f;
						m_v.y = 0.0f;
						currentObj = vecGameObjs[i];
						if (!m_bIsRight)
						{
							if (m_pos.x <= currentObj->GetBox().x)
								if (rand() % 100 < 70)
								{
								m_nStatus = ENEMY_JUMP;
								m_bIsJumping = true;
								}
								else
								{
									m_bIsRight = !m_bIsRight;
									m_v.x = -m_v.x;
								}
						}
						else
						{
							if (m_pos.x >= currentObj->GetBox().x + currentObj->GetBox().width)
								if (rand() % 100 < 50)
								{
								m_nStatus = ENEMY_JUMP;
								m_bIsJumping = true;
								}
								else
								{
									m_bIsRight = !m_bIsRight;
									m_v.x = -m_v.x;
								}
						}
					}
					break;

				case ID_WATER:
					m_nCount++;
					if (m_nStatus != ENEMY_JUMP)
					{
						m_bIsJumping = true;
						m_nStatus = ENEMY_JUMP;
						if (!m_bIsRight)
						{
							m_v.x = -100.0f;
						}
						else
						{
							m_v.x = 100.0f;
						}
						m_v.y = 200.0f;
					}
					else
					{
						m_bIsFallInWater = true;
						m_fTimeDie = 0.05f;
						m_nCount = 0;
						m_nStatus = ENEMY_DIE;
						m_bIsLive = false;
						return;
					}
					break;
				}
			}
		}
	}
	// Update vị trí.
	m_pos += m_v * timeFrame;
	m_v += m_a * timeFrame;
}

void CRunningMan::Draw()
{
	if (!m_bIsLive && m_fTimeDie == 0.0f)
		return;
	D3DXVECTOR2 pos = CViewport::GetInstance()->TransformMatrix(m_pos);
	if (!m_bIsRight)
		m_pSprite->DrawFlipX(pos);
	else
		m_pSprite->Draw(pos);
	RECT rect;
	rect.left = m_box.x - m_box.width / 2.0f;
	rect.top = m_box.y + m_box.height / 2.0f;
	rect.right = m_box.x + m_box.width / 2.0f;
	rect.bottom = m_box.y - m_box.height / 2.0f;
	D3DXVECTOR2 pos_box = CViewport::GetInstance()->TransformMatrix(D3DXVECTOR2(m_box.x + m_box.width / 2.0f, m_box.y - m_box.height / 2.0f));
	//m_pTextureBox->DrawRect(pos_box, rect);
}

void CRunningMan::Reset(D3DXVECTOR2 pos, bool direction)
{
	m_bIsLive = true;
	m_pos = pos;
	m_bIsFallInWater = false;
	m_bIsFired = false;
	m_bIsFiring = false;
	timeFire = 1.0f;
	m_nStatus = ENEMY_RUN;
	m_v.y = ENEMY_VY;
	m_nCount = 0;
	m_bIsRight = direction;
	if (m_bIsRight)
		m_v.x = -ENEMY_VX;
	else
		m_v.x = ENEMY_VX;
	m_a.y = GRAVITY;
}

void CRunningMan::Explode()
{
	if (!m_bIsFallInWater)
	{
		CExplosion *ex = new CExplosion(m_pos, 0, ID_ENEMY_EXPLOSION, false, 0.18f);
		CPlayState::s_objsOutSideQuadTree.push_back(ex);
	}
	else
	{
		CExplosion *ex = new CExplosion(m_pos, 0, ID_ENEMY_FALL_IN_WATER, false, 0.18f);
		CPlayState::s_objsOutSideQuadTree.push_back(ex);
	}
}

void CRunningMan::Fire()
{
	D3DXVECTOR2 bulletPos;

	bulletPos.y = m_pos.y + m_pSprite->GetHeight() / 2.0f - 23.0f;
	if (m_bIsRight)
	{
		m_pGun->SetBulletAngle(0);
		bulletPos.x = m_pos.x + m_pSprite->GetWidth() / 2.0f;
	}
	else
	{
		m_pGun->SetBulletAngle(180);
		bulletPos.x = m_pos.x - m_pSprite->GetWidth() / 2.0f;
	}
	
	m_pGun->Fire(bulletPos);

	m_bIsFired = true;
	m_bIsFiring = true;
	timeFire = 0.3f;
}
